/*
	* Created by : Varun Tyagi
	*
	* This tutorial is going to check the key presses without using events. This is possible due to keystates
	* Sometimes just checking if a key is up or down is far easier and better than monitoring events. 
*/

/* Include the header files. */
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_ttf.h"
#include <string>

/* Screen Attributes. */
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

/* Surfaces. */
SDL_Surface *pBackground = nullptr;
SDL_Surface *pUp = nullptr;
SDL_Surface *pDown = nullptr;
SDL_Surface *pLeft = nullptr;
SDL_Surface *pRight = nullptr;
SDL_Surface *pScreen = nullptr;

/* The event structure. */
SDL_Event event;

/* The font. */
TTF_Font *pFont = nullptr;

/* Text color. */
SDL_Color textColor = { 0, 0, 0 };

/* Image loader. */
SDL_Surface *load_image( std::string filename )
{
	/* The image that's loaded. */
	SDL_Surface *pLoadedImage = nullptr;

	/* The optimized image. */
	SDL_Surface *pOptimizedImage = nullptr;

	/* Load the image. */
	pLoadedImage = IMG_Load( filename.c_str() );

	/* If we correctly loaded the image, then optimize it. */
	if( nullptr != pLoadedImage )
	{
		/* Create an optimized image. */
		pOptimizedImage = SDL_DisplayFormat( pLoadedImage );

		/* Free the old surface. */
		SDL_FreeSurface( pLoadedImage );

		/* If the image has been optimized then, color key surface. */
		if( nullptr != pOptimizedImage )
		{
			SDL_SetColorKey( pOptimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( pOptimizedImage->format, 0, 0xFF, 0xFF ) );
		}
	}

	/* Return the optimized image. */
	return pOptimizedImage;
}

/* Surface applier. */
void apply_surface( int x, int y, SDL_Surface *pSource, SDL_Surface *pDestination, SDL_Rect *pClip = nullptr )
{
	/* Holds offset. */
	SDL_Rect offset;

	offset.x = x;
	offset.y = y;

	/* Blit the surface. */
	SDL_BlitSurface( pSource, pClip, pDestination, &offset );
}

/* Init SDL. */
bool init_SDL( void )
{
	/* Initialize all SDL subsystems. */
	if( SDL_Init( SDL_INIT_EVERYTHING ) )
	{
		return false;
	}

	/* Set up the screen. */
	pScreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

	/* Check to see if the screen has been set up properly. */
	if( nullptr == pScreen )
	{
		return false;
	}

	/* Initialize the font. */
	if( -1 == TTF_Init() )
	{
		return false;
	}

	/* Set the window caption. */
	SDL_WM_SetCaption( "KeyPress Tutorial", nullptr );

	/* If everything went well, return 1. */
	return true;
}

/* File loader. */
bool load_file( void )
{
	/* Load the background image. */
	pBackground = load_image( "background.png" );

	/* Open the font. */
	pFont = TTF_OpenFont( "lazy.ttf", 72 );

	/* Check to see if the background has been loaded properly. */
	if( nullptr == pBackground )
	{
		return false;
	}

	/* Check to see if the font has been loaded properly. */
	if( nullptr == pFont )
	{
		return false;
	}

	/* If everything went well, return true. */
	return true;
}

/* Clean up. */
void clean_up( void )
{
	/* Free the surface. */
	SDL_FreeSurface( pBackground );
	SDL_FreeSurface( pUp );
	SDL_FreeSurface( pDown );
	SDL_FreeSurface( pLeft );
	SDL_FreeSurface( pRight );

	/* Close the font. */
	TTF_CloseFont( pFont );

	/* QUIT Font. */
	TTF_Quit();

	/* QUIT SDL. */
	SDL_Quit();
}

/* Main. */
int main( int argc, char** argv )
{
	/* QUIT flag. */
	bool bQuit = false;

	/* Initialize. */
	if( false == init_SDL() )
	{
		return 1;
	}

	/* Load files. */
	if( false == load_file() )
	{
		return 1;
	}

	/* Render the text. */
	pUp = TTF_RenderText_Solid( pFont, "UP", textColor );
	pDown = TTF_RenderText_Solid( pFont, "DOWN", textColor );
	pRight = TTF_RenderText_Solid( pFont, "RIGHT", textColor );
	pLeft = TTF_RenderText_Solid( pFont, "LEFT", textColor );

	/* While the user hasn't quit. */
	while( false == bQuit )
	{
		/* While there is event to handle. */
		while( SDL_PollEvent( &event ) )
		{
			/* If the user has Xed out the window. */
			if( SDL_QUIT == event.type )
			{
				/* Quit the program. */
				bQuit = true;
			}
		}

		/* Apply the background. */
		apply_surface( 0, 0, pBackground, pScreen );

		/* Get the keystates. */
		Uint8 *keyStates = SDL_GetKeyState( nullptr );

		/* If up is pressed. */
		if( keyStates[ SDLK_UP ] || keyStates[ SDLK_KP8 ] )
		{
			apply_surface( (SCREEN_WIDTH - pUp->w) / 2, (SCREEN_HEIGHT / 2 - pUp->h) / 2, pUp, pScreen );
		}

		/* If down is pressed. */
		if( keyStates[ SDLK_DOWN ] || keyStates[ SDLK_KP2 ] )
		{
			apply_surface( (SCREEN_WIDTH - pDown->w) / 2, ( (SCREEN_HEIGHT / 2 - pDown->h) / 2 ) + ( SCREEN_HEIGHT / 2 ), pDown, pScreen );
		}

		/* If right is pressed. */
		if( keyStates[ SDLK_RIGHT ] || keyStates[ SDLK_KP6 ] )
		{
			apply_surface( ( (SCREEN_WIDTH - pRight->w) / 2 ) + (SCREEN_WIDTH / 2), (SCREEN_HEIGHT  - pRight->h) / 2, pRight, pScreen );
		}

		/* If left is pressed. */
		if( keyStates[ SDLK_LEFT ] || keyStates[ SDLK_KP4 ] )
		{
			apply_surface( (SCREEN_WIDTH / 2 - pLeft->w ) / 2, (SCREEN_HEIGHT - pLeft->h) / 2, pLeft, pScreen );
		}

		/* Update the scree. */
		if( -1 == SDL_Flip( pScreen ) )
		{
			return 1;
		}
	}

	/* Clean up. */
	clean_up();

	return 0;
}